"""
数二进制中的1
3 0000 0011
5 0000 0101
&----------
  0000 0001

3 0000 0011
5 0000 0101
|----------
  0000 0111

3 0000 0011
5 0000 0101
^----------
  0000 0110

3 0000 0011
~----------
  1111 1100

3 0000 0011
3 0000 0011
^----------
  0000 0000
3 0000 0011
^----------
  0000 0011

摘要 - MD5/SHA1/SHA256 - 单向哈希函数
    ~ hashlib ---> md5() / sha1() / sha256()
编码/解码 - BASE64 / 百分号编码
    ~ 百分号编码
        - urllib.parse ---> quote() / unquote()
    ~ Base64是一种基于64个可打印字符来表示二进制数据的表示方法
        - base64 ---> b64encode() / b64decode()
加密/解密
    ~ 对称加密 - 加密和解密是同一个密钥 - AES
    ~ 非对称加密 - 加密和解密是不同的密钥 - RSA
        - pycrypto
序列化/反序列化
    ~ 序列化 - 把对象变成字符串(str)或字节串(bytes) - 串行化/冻结
        - json / pickle - dump / dumps
    ~ 反序列化 - 把字符串或字节串还原成对象 - 反串行化/解冻
        - json / pickle - load / loads
    ~ Python内置的json序列化性能较差，实际开发中通常用ujson三方库取代它
    ~ 猴子补丁（monkey patch） - 动态替换
    ~ 鸭子类型（duck typing) - 认定对象类型主要看行为
面试题：HTTPS工作原理
"""
import json
import ujson

# ujson.__name__ = 'json'
# json.dumps = ujson.dumps
# json.loads = ujson.loads

# from example02 import Person


# class PersonJsonEncoder(json.JSONEncoder):

#     def default(self, obj):
#         return {
#             'name': obj.name,
#             'age': obj.age
#         }


# person = Person('王大锤', 25)
# print(json.dumps(person, cls=PersonJsonEncoder))


# from io import StringIO

# message = '仐夳晀丐佺语戋吙饷'
# buffer = StringIO()
# key = 0x1a
# for ch in message:
#     buffer.write(chr(ord(ch) ^ key))
# print(buffer.getvalue())


def count_one1(num):
    counter = 0
    while num:
        if num & 1:
            counter += 1
        num = num >> 1
    return counter


def count_one2(num):
    counter = 0
    while num:
        counter += 1
        num = num & (num - 1)
    return counter


# # 0001 1110
# print(count_one1(30))
# print(count_one2(30))
# # 0001 1111
# print(count_one1(31))
# print(count_one2(31))
# # 0010 0000
# print(count_one1(32))
# print(count_one2(32))

"""
n = 30 ===> 0001 1110
    29 ===> 0001 1101
&---------------------
            0001 1100
            0001 1011
&---------------------
            0001 1000    
n & n-1
"""
# import hashlib

# from Crypto.Cipher import AES
# from Crypto import Random

# key = hashlib.md5(b'my_secret_key').hexdigest()
# iv = Random.new().read(AES.block_size)
# plain_text = 'hello, world!'
# cipher_text = AES.new(key, AES.MODE_CFB, iv).encrypt(plain_text)
# print(cipher_text)
# plain_text = AES.new(key, AES.MODE_CFB, iv).decrypt(cipher_text).decode()
# print(plain_text)

from Crypto.PublicKey import RSA

# 生成密钥对
key_pair = RSA.generate(2048)
# 获取公钥
pub_key = RSA.importKey(key_pair.publickey().exportKey())
plain_text = 'hello, world!'
# 使用公钥加密数据
cipher_text = pub_key.encrypt(plain_text.encode(), None)
print(cipher_text)
# 获取私钥
pri_key = RSA.importKey(key_pair.exportKey())
# 使用私钥解密数据
plain_text = pri_key.decrypt(cipher_text)
print(plain_text)
